package Domain;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.joda.time.LocalDate;
import org.joda.time.LocalTime;
import org.uqbar.commons.model.ObservableUtils;
import org.uqbar.commons.utils.Observable;

import Exceptions.DisponibilidadYaSeteadaException;
import Exceptions.IntervaloNoValidoException;

@Observable
public class Empleado {
	private String nombreYApellido = "";
	private String legajo = "";
	// private Map<Dia, Interval> disponibilidad;
	private List<Disponibilidad> disponibilidad;
	private List<Compromiso> compromisos;
	// si el turno asignado es != NULL el empleado ya está ocupado
	private Turno turnoAsignado;
	private Map<LocalDate, Asignacion> asignaciones;

	public Empleado() {
		this.disponibilidad = new ArrayList<Disponibilidad>();
		this.compromisos = new ArrayList<Compromiso>();
	}

	public void agregarDisponibilidad(Disponibilidad disp)
			throws IntervaloNoValidoException, DisponibilidadYaSeteadaException {
		int CUATRO_HORAS = 14400000;

		if (disp.getIntervalo().toDurationMillis() < CUATRO_HORAS) {
			throw new IntervaloNoValidoException();
		}
		if (this.getDisponibilidad().contains(disp.getDia())) {
			throw new DisponibilidadYaSeteadaException();
		}
		this.getDisponibilidad().add(disp);
	}

	public String getEstadoEn(LocalDate fechaTurno, LocalTime horaDesde,
			LocalTime horaHasta) {
		if (horaDesde == null || horaHasta == null) {
			return "completar horas del turno";
		}
		if (this.estoyDisponiblePara(fechaTurno, horaDesde, horaHasta)
				&& (!this.tengoAsignacionesEnTurno(fechaTurno))) {
			return "SI, puede";
		} else {
			// NO PUEDE, YA ESTÁ ASIGNADO
			if (this.tengoAsignacionesEnTurno(fechaTurno)) {
				return "No puede, ya está asignado";
			} else {
				// NO PUEDE, TIENE UN COMPROMISO
			}
			if (this.getCompromisos().contains(fechaTurno)) {
				return "no puede, tiene un compromiso";
				// NO TIENE DISPONIBILIDAD
			} else {
				if (!this.estoyDisponiblePara(fechaTurno, horaDesde, horaHasta)) {
					return "no tiene disponibilidad a esa hora";
				} else {
					return "ni idea";
				}
			}
		}
	}

	public void agregarCompromiso(Compromiso c) {
		this.getCompromisos().add(c);
	}

	public boolean tengoCompromisosEn(LocalDate ld) {
		return this.getCompromisos().contains(ld);
	}

	public boolean disponibleDia(Dia d) {
		// return this.getDisponibilidad().containsKey(d);
		boolean esta = false;
		for (Disponibilidad dispo : this.getDisponibilidad()) {
			esta = esta | (dispo.getDia().equals(d));
		}
		return esta;
	}

	public Dia getDescripcionDeDisponibilidadRequerida(LocalDate fecha) {
		return Dia.getDiaPara(fecha.getDayOfWeek());
	}

	public Disponibilidad getDisponibilidadPara(LocalDate fecha) {
		Disponibilidad disp = null;
		for (Disponibilidad dispo : this.getDisponibilidad()) {
			if (dispo.getDia().equals(
					this.getDescripcionDeDisponibilidadRequerida(fecha))) {
				disp = dispo;
			}
		}
		return disp;

	}

	public boolean estoyDisponiblePara(LocalDate fecha, LocalTime desde,
			LocalTime hasta) {
		// la disponibilidad de ese empleado para el dia de ese turno
		boolean dispo = false;
		dispo = (this.disponibleDia(this
				.getDescripcionDeDisponibilidadRequerida(fecha)))
				&& this.getDisponibilidadPara(fecha).contiene(desde, hasta)
				&& !tengoCompromisosEn(fecha);

		return dispo;

	}

	public boolean tengoAsignacionesEnTurno(LocalDate fechaTurno) {
		return (this.getAsignaciones().get(fechaTurno) != null);
	}

	// ////////////////////////////////////ACCESORS////////////////////////
	public String getNombreYApellido() {
		return nombreYApellido;
	}

	public void setNombreYApellido(String nombreYApellido) {
		this.nombreYApellido = nombreYApellido;
	}

	public String getLegajo() {
		return legajo;
	}

	public void setLegajo(String legajo) {
		this.legajo = legajo;
	}

	public List<Compromiso> getCompromisos() {
		return compromisos;
	}

	public void setCompromisos(ArrayList<Compromiso> compromisos) {
		this.compromisos = compromisos;
	}

	public ArrayList<Disponibilidad> getDisponibilidad() {
		return (ArrayList<Disponibilidad>) disponibilidad;
	}

	public void setDisponibilidad(ArrayList<Disponibilidad> disponibilidad) {
		this.disponibilidad = disponibilidad;
	}

	public Turno getTurnoAsignado() {
		return turnoAsignado;
	}

	public void setTurnoAsignado(Turno turnoAsignado) {
		this.turnoAsignado = turnoAsignado;
	}

	public Map<LocalDate, Asignacion> getAsignaciones() {
		return asignaciones;
	}

	public void setAsignaciones(Map<LocalDate, Asignacion> asignaciones) {
		this.asignaciones = asignaciones;
	}

	public ArrayList<Dia> getDias() {
		ArrayList<Dia> dispos = new ArrayList<Dia>();
		for (Disponibilidad disp : this.getDisponibilidad()) {
			dispos.add(disp.getDia());
		}
		return dispos;
	}

	public String getKeysDisponibilidad() {
		// return this.disponibilidad.keySet().toString();
		String dispo = "";
		for (Disponibilidad dis : this.getDisponibilidad()) {
			dispo = dispo + dis.getDia().toString() + ", ";
		}
		return dispo;
	}

	public String getDescripcionEntera() {
		return this.nombreYApellido + " Legajo: " + this.legajo;

	}

	public void removerDisponibilidad(Disponibilidad disponibilidadSeleccionada) {
		this.getDisponibilidad().remove(disponibilidadSeleccionada);
		ObservableUtils.firePropertyChanged(this, "disponibilidad",
				this.getDisponibilidad());
	}

}